//if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
#include "LOK2ChatInput.h"
LOK2ChatInput::	LOK2ChatInput(SDL_Surface *_screen, TTF_Font *_font, SDL_Color _textColor, SDL_Event *_event, SDLClipboard *_pClipboard,
		LOK2ChatMessageHandler *pChatMsgHandler, const char *bgFileName, int _max_len) {
	screen = _screen;
	font = _font;
	event = _event;
	max_len = _max_len;
	textColor = _textColor;
	lines = 1;
	pClipboard = _pClipboard;
	if(bgFileName) textBoxBody = load_image(bgFileName);
	else textBoxBody = 0;
	SDL_EnableUNICODE(SDL_ENABLE);
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
	caretTimer = SDL_AddTimer(500, pToggleCaret, this);
	caret.caretOn = true;
	caret.caretOff = false;
	caret.caretLoc = 0;
	caret.caretX = 0;
	caret.caretY = 0;
	caret.caretH = 0;
	box.x = 5;
	box.y = SCREEN_HEIGHT;
	box.w = SCREEN_WIDTH;
	box.h = 0;
	highlight.active = false;
	highlight.start = -1;
	highlight.stop = -1;
	normalCursor = SDL_GetCursor();
	textCursor = SDL_MakeCursor(textCursorBMP);
	vector <pair <string, bool> > popupMenuInit;
	string label1 = "Cut";
	string label2 = "Copy";
	string label3 = "Paste";
	string label4 = "Select All";
	string label5 = "Delete";
	popupMenuInit.push_back(make_pair(label1, false));
	popupMenuInit.push_back(make_pair(label2, false));
	popupMenuInit.push_back(make_pair(label3, false));
	popupMenuInit.push_back(make_pair(label4, false));
	popupMenuInit.push_back(make_pair(label5, false));
	SDL_Color popupNormal = {0xFF, 0xFF, 0x00};
	SDL_Color popupGrayed = {0x77, 0x77, 0x22};
	pPopupMenu = new SDLPopupMenu(popupMenuInit, popupNormal, popupGrayed, screen, event, font, this);
	setFocus(false);
	m_pChatMsgHandler = pChatMsgHandler;
}

void LOK2ChatInput::display() {
	int i = 0;
	box.h = 0;
	box.y = SCREEN_HEIGHT;
	int w = 0, h = 0;
	lines = makeLines(615);
	if(str.size() > 0) {
		SDL_Surface *apply = 0;
		vector <SDL_Surface *> buffer;
		for(i = 0; i < vLines.size(); i++) {
			apply = TTF_RenderText_Solid(font, vLines[i].c_str(), textColor);
			box.h += apply->h;
			//box.y -= apply->h;
			if(textBoxBody) apply_surface(0, (SCREEN_HEIGHT - (apply->h * (i + 1) + 5)), textBoxBody, screen);
			apply_surface(5, (SCREEN_HEIGHT - (apply->h * ((lines - (i + 1)) + 1))), apply, screen);
			buffer.push_back(apply);
			buffer[i]->refcount++;
			for(int k = 0; k < i; k++) apply_surface(5, (SCREEN_HEIGHT - (buffer[i]->h * (lines - k))), buffer[k], screen);
			SDL_FreeSurface(apply);
		}
		if(vLines.size() > 1) pManager->requestLock(this);
		//else pManager->releaseLock(this);
		for(i = 0; i < buffer.size(); i++) SDL_FreeSurface(buffer[i]);
		buffer.clear();
	}
	int last = 0;
	bool caretDrawn = false;
	if(caret.caretOn) {
		int w2 = 0;
		for(int i = 0; i < vLines.size(); i++) {
			if(caret.caretLoc <= vLines[i].size() + last && !caretDrawn) {
				TTF_SizeText(font, vLines[i].substr(0, caret.caretLoc - last).c_str(), &w, &h);
				caret.caretX = (5 + w);
				caret.caretY = (SCREEN_HEIGHT - (h * (vLines.size() - i)));
				caret.caretH = h;
				draw_line(screen, caret.caretX, caret.caretY, caret.caretH, 0xffff00);
				caretDrawn = true;
			}
			last += vLines[i].size();
		} if(vLines.size() == 0) {
			caret.caretX = 5;
			caret.caretY = SCREEN_HEIGHT - 16;
			caret.caretH = 16;
			draw_line(screen, caret.caretX, caret.caretY, caret.caretH, 0xffff00);
			caretDrawn = true;
		}
		caret.caretOn = false;
		caret.caretOff = true;
	}
	if(highlight.start != highlight.stop) doHighlight();
	if(pPopupMenu->isVisible()) {
		if(pPopupMenu->mustRender()) pPopupMenu->render();
		pPopupMenu->show(mousePos.x, mousePos.y);
		pPopupMenu->doHighlight(pPopupMenu->getCurrentItem());
	}
}

SDL_Rect LOK2ChatInput::getRect() {
	SDL_Rect ret;
	ret.x = box.x;
	if(box.h > 0) ret.y = box.y - box.h;
	else ret.y = box.y - 16;		//hacky
	//ret.y = box.y;
	if(box.h > 0) ret.h = box.h;
	else ret.h = 16 ;				//still hacky
	ret.w = box.w;
	return ret;
}

void LOK2ChatInput::inputHandler() {
//	if(event->type == SDL_MOUSEBUTTONDOWN) setFocus(true);
	SDL_Rect box2 = getRect();	//different like wow
	std::string buffer;
	if(pPopupMenu->isVisible()) {
		if(highlight.start != highlight.stop) { 
			pPopupMenu->setActive(POPUP_CUT, true);
			pPopupMenu->setActive(POPUP_COPY, true);
			pPopupMenu->setActive(POPUP_DELETE, true);
		} else {
			pPopupMenu->setActive(POPUP_CUT, false);
			pPopupMenu->setActive(POPUP_COPY, false);
			pPopupMenu->setActive(POPUP_DELETE, false);
		}
		if(str.size() > 0) {
			pPopupMenu->setActive(POPUP_SELECTALL, true);
		} else {
			pPopupMenu->setActive(POPUP_SELECTALL, false);
		}
		if(buffer.size() < 1) {
			pPopupMenu->setActive(POPUP_PASTE, true);
		} else {
			pPopupMenu->setActive(POPUP_PASTE, false);
		}
		SDL_SetCursor(normalCursor);
		pPopupMenu->inputHandler();
	}
	if(hasFocus()) {
		int x, y;
		int caretLocBuffer = -1;
		string temp;
		switch(event->type) {
		case SDL_KEYDOWN:
			switch(event->key.keysym.sym) {
			case SDLK_BACKSPACE:
				if(str.length() != 0 && caret.caretLoc > 0) {
					if(highlight.start != highlight.stop) {
						if(highlight.start > highlight.stop) {
							x = highlight.stop;
							y = highlight.start;
						} else {
							x = highlight.start;
							y = highlight.stop;
						}
						str.erase(x, y - x);
						caret.caretLoc = x;
						highlight.start = -1;
						highlight.stop = -1;
					} else {
						str.erase(caret.caretLoc - 1, 1);
						caret.caretLoc--;
					}
				}
				break;
			case SDLK_DELETE:
				if(caret.caretLoc < str.size()) {
					if(highlight.start != highlight.stop) {
						if(highlight.start > highlight.stop) {
							x = highlight.stop;
							y = highlight.start;
						} else {
							x = highlight.start;
							y = highlight.stop;
						}
						str.erase(x, y - x);
						caret.caretLoc = x;
						highlight.start = -1;
						highlight.stop = -1;
					} else str.erase(caret.caretLoc, 1);
				}
				break;
			case SDLK_HOME:
				highlight.active = false;
				highlight.start = -1;
				highlight.stop = -1;
				caret.caretLoc = 0;
				break;
			case SDLK_END:
				highlight.active = false;
				highlight.start = -1;
				highlight.stop = -1;
				caret.caretLoc = str.size();
				break;
			case SDLK_RETURN:
				if(str.size() > 0) {
					sendChatMessage("User 1: ", str, 0);
					highlight.active = false;
					highlight.start = -1;
					highlight.stop = -1;
					caret.caretLoc = 0;
					str.erase();
				}
				break;
			default:
				//left, right, up, down have to be in default so that ctrl-dir will work for highlighting.
				if(event->key.keysym.sym == SDLK_LEFT) {
					highlight.active = false;
					highlight.start = -1;
					highlight.stop = -1;
					if(caret.caretLoc > 0) caret.caretLoc--;
				}
				if(event->key.keysym.sym == SDLK_RIGHT) {
					highlight.active = false;
					highlight.start = -1;
					highlight.stop = -1;				
					if(caret.caretLoc < str.length()) caret.caretLoc++;
				}
				if(event->key.keysym.sym == SDLK_UP) {
					highlight.active = false;
					highlight.start = -1;
					highlight.stop = -1;
					if(findCharXY(caret.caretX, caret.caretY - caret.caretH / 2) > 0) caret.caretLoc = findCharXY(caret.caretX, caret.caretY - caret.caretH / 2);
					else caret.caretLoc = 0;
				}
				if(event->key.keysym.sym == SDLK_DOWN) {
					highlight.active = false;
					highlight.start = -1;
					highlight.stop = -1;
					if(findCharXY(caret.caretX, caret.caretY + (caret.caretH + caret.caretH / 2)) > 0) caret.caretLoc = findCharXY(caret.caretX, caret.caretY + (caret.caretH + caret.caretH / 2));
					else caret.caretLoc = str.size();
				}

				if(str.length() <= max_len) {
					if(event->key.keysym.unicode >= 0x20 && event->key.keysym.unicode <= 0x7E) {
						pManager->requestLock(this);
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							if(y > str.size()) y = str.size();
							if(str.substr(x, y - x).size() > 0) str.erase(x, y - x);
							highlight.start = -1;
							highlight.stop = -1;
							highlight.active = false;
							caret.caretLoc = x;
						}
						temp = (char)event->key.keysym.unicode;
						str.insert(caret.caretLoc, temp);
						caret.caretLoc++;
					}
				}
				if(event->key.keysym.mod & KMOD_CTRL) {
					switch(event->key.keysym.sym) {
					case 'a':
						highlight.start = 0; //should be 0, fix when I go through and make 0 an acceptable index for highlighting
						highlight.stop = str.size();
						highlight.active = true;
						break;
					case 'c':
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
						}
						break;
					case 'v':
						if(pClipboard->getData().size() > 0) {
							if(highlight.start == highlight.stop) {
								temp = pClipboard->getData();
								if(temp.size() > 0) {
									if(str.size() + temp.size() > max_len) {
										x = max_len - str.size();
										temp.erase(x, temp.size() - x);
									}
									str.insert(caret.caretLoc, temp);
									caret.caretLoc += temp.size();
								}
							} else {
								if(highlight.start > highlight.stop) {
									x = highlight.stop;
									y = highlight.start;
								} else {
									x = highlight.start;
									y = highlight.stop;
								}
								temp = str.substr(x, y - x);
								str.erase(x, y - x);
								caret.caretLoc = y;
								caret.caretLoc -= temp.size();
								temp = pClipboard->getData();
								if(str.size() + temp.size() > max_len) {
									x = max_len - str.size();
									temp.erase(x, temp.size() - x);
								}
								str.insert(caret.caretLoc, temp);
								highlight.start = -1;
								highlight.stop = -1;
								caret.caretLoc += temp.size();
							}
						}
						break;
					case 'x':
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							if(y > str.size()) y = str.size();
							if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
							str.erase(x, y - x);
							caret.caretLoc = x;
							highlight.start = -1;
							highlight.stop = -1;
						}
						break;
					case SDLK_LEFT:
						if(highlight.active) {
							if(highlight.stop == caret.caretLoc + 1) {
								highlight.stop = caret.caretLoc;
							} else {
								highlight.start = caret.caretLoc + 1;
								highlight.stop = caret.caretLoc;
							}
						} else {
							highlight.start = caret.caretLoc + 1;
							highlight.stop = caret.caretLoc;
							highlight.active = true;
						}
						break;
					case SDLK_RIGHT:
						if(highlight.active) {
							if(highlight.stop == caret.caretLoc - 1) {
								highlight.stop = caret.caretLoc;
							} else {
								highlight.start = caret.caretLoc - 1;
								highlight.stop = caret.caretLoc;
							}
						} else {
							highlight.start = caret.caretLoc - 1;
							highlight.stop = caret.caretLoc;
							highlight.active = true;
						}
						break;
					case SDLK_UP:		//not too sure why up and down work the same here..
					case SDLK_DOWN:
						x = findCharXY(caret.caretX, caret.caretY + caret.caretH / 2);
						if(highlight.active) {
							if(highlight.stop == x - 1 || highlight.stop == x + 1 || highlight.stop == x) {
								highlight.stop = caret.caretLoc;
							} else {
								highlight.start = x;
								highlight.stop = caret.caretLoc;
							}
						} else {
							highlight.start = x;
							highlight.stop = caret.caretLoc;
							highlight.active = true;
						}
						break;
					case 'k':
						str.erase();
						caret.caretLoc = 0;
						highlight.active = false;
						highlight.start = -1;
						highlight.stop = -1;
						break;
					}
				}
			}
			break;
		case SDL_MOUSEBUTTONDOWN:		//this is different from SDLTextBox's version in that it sets box 2
										//to the output from getRect(); ..since this scrolls bottom to top it
			switch(event->button.button) {	//behaves differently from other SDLTextBox's
			case SDL_BUTTON_LEFT:
				x = event->button.x;
				y = event->button.y;
				if((x > box2.x) && (x < box2.x + box2.w) && (y > box2.y) && (y < box2.y + box2.h)) {
					pManager->requestLock(this);
					caretLocBuffer = findCharXY(x, y);
					if(caretLocBuffer != -1) {
						if(caretLocBuffer < str.size()) highlight.stop = caretLocBuffer;
						else highlight.stop = str.size();
						if(!highlight.active) {
							highlight.start = -1;
							highlight.stop = -1;
							highlight.start = caretLocBuffer;
							highlight.active = true;
						}
					}
					caret.caretLoc = ((caretLocBuffer < str.size()) ? caretLocBuffer : str.size());
					if(pPopupMenu->isVisible()) pPopupMenu->hide();
				} else pManager->releaseLock(this);
				break;
			case SDL_BUTTON_RIGHT:
				x = event->button.x;
				y = event->button.y;
				if((x > box2.x) && (x < box2.x + box2.w) && (y > box2.y) && (y < box2.y + box2.h)) {
					pManager->requestLock(this);
					mousePos.x = x;
					mousePos.y = y;
					if(pPopupMenu->mustRender()) pPopupMenu->render();
					pPopupMenu->show(mousePos.x, mousePos.y);
				} else pManager->releaseLock(this);
				break;
			}
			break;
		case SDL_MOUSEMOTION:
			x = event->motion.x;
			y = event->motion.y;
			if((x > box2.x) && (x < box2.x + box2.w) && (y > box2.y) && (y < box2.y + box2.h)) {
				SDL_SetCursor(textCursor);
			} else {
				SDL_SetCursor(normalCursor);
			}
			if(event->motion.state & SDL_BUTTON(1)) {
				if((x > box2.x) && (x < box2.x + box2.w) && (y > box2.y) && (y < box2.y + box2.h)) {
					if(!highlight.active) {
						highlight.start = -1;
						highlight.stop = -1;
						caretLocBuffer = findCharXY(x, y);
						if(caretLocBuffer) highlight.start = caretLocBuffer;
						highlight.active = true;
					} else if(highlight.active) {
						caretLocBuffer = findCharXY(x, y);
						if(caretLocBuffer != -1) {
							if(caretLocBuffer < str.size()) highlight.stop = caretLocBuffer;
							else highlight.stop = str.size();
						}
						caret.caretLoc = ((caretLocBuffer < str.size()) ? caretLocBuffer : str.size());
					}
				}
			}
			break;
		case SDL_MOUSEBUTTONUP:
			if(event->button.button == SDL_BUTTON_LEFT) {
				x = event->button.x;
				y = event->button.y;
				if(highlight.active) {
					caretLocBuffer = findCharXY(x, y);
					if(caretLocBuffer != - 1) {
						if(caretLocBuffer <= str.size()) highlight.stop = caretLocBuffer;
						else highlight.stop = str.size();
					} 
					highlight.active = false;
				} else {
					highlight.start = -1;
					highlight.stop = -1;
				}
				caret.caretLoc = ((caretLocBuffer < str.size()) ? caretLocBuffer : str.size());
			}
			break;
		default:
			//unknown event
			break;
		}
	}
}

int LOK2ChatInput::findCharXY(int x, int y) {
	caret.debugX = x;
	caret.debugY = y;
	SDL_Rect box2 = getRect();
	string buffer = str;
	int w = 0, h = 0, i = 0, j = 1, last = 0;
	for(i = 0; i < vLines.size(); i++) {
		j = 1;
		do {
			TTF_SizeText(font, vLines[i].substr(0, j++).c_str(), &w, &h);
		} while(w < x - box2.x && j <= vLines[i].size());
		if(i > 0) last += vLines[i - 1].size();
		if(y >= (box2.y + (i * h)) && y <= (box2.y + ((i + 1) * h))) {
			TTF_SizeText(font, vLines[i].substr(0, last + j - 1 + (i > 0 ? 1: 0)).c_str(), &w, NULL);
			TTF_SizeText(font, vLines[i].substr(0, last + j - 2 + (i > 0 ? 1: 0)).c_str(), &h, NULL);
			if(x < box2.x + (w - ((w - h) / 2))) return last + j - 2 + (i > 0 ? 1: 0);  //this stuff should probably be floats
			else return last + j - 1 + (i > 0 ? 1 : 0);
		}
	}
	return -1;
}

void LOK2ChatInput::doHighlight() {
	SDL_Rect box2 = getRect();
	int last = -1;
	SDL_Rect dst, dst2;
	dst.x = 0;
	dst.y = 0;
	dst.w = 0;
	dst.h = 0;
	dst2.x = 0;
	dst2.y = 0;
	dst2.w = 0;
	dst2.h = 0;
	SDL_Surface *highlightSurface = 0; 
	int w = 0, h = 0;

	int start = 0, stop = 0;
	bool startFound = false, done = false;
	if(highlight.start < highlight.stop) {
		start = highlight.start;
		stop = highlight.stop;
	} else {
		start = highlight.stop;
		stop = highlight.start;
	}
	//if(start == 0) start = 1;
	for(int i = 0; i < vLines.size(); i++) {
		if(!done) {
			if(startFound) {
				if(stop - last > vLines[i].size()) {
					TTF_SizeText(font, vLines[i].c_str(), &w, &h);
					dst.x = 0;
					dst.h = h;
					dst.w = w;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box2.x + dst.x, box2.y + dst.y, highlightSurface, screen);
				} else {
					TTF_SizeText(font, vLines[i].substr(0, stop - last).c_str(), &w, &h);
					dst.x = 0;
					dst.h = h;
					dst.w = w;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box2.x + dst.x, box2.y + dst.y, highlightSurface, screen);
					done = true;
				}
			} else if(start < vLines[i].size() + last && start > last) {
				if(last == -1) last = 0;
				startFound = true;
				if(stop - last > vLines[i].size()) {
					TTF_SizeText(font, vLines[i].substr(0, start - last).c_str(), &w, &h);
					dst.x = w;
					dst.h = h;
					TTF_SizeText(font, vLines[i].substr(start - last, vLines[i].size() - (start - last)).c_str(), &w, &h);
					dst.w = w;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box2.x + dst.x, box2.y + dst.y, highlightSurface, screen);
				} else {
					TTF_SizeText(font, vLines[i].substr(0, start - last).c_str(), &w, &h);
					dst.x = w;
					dst.h = h;
					TTF_SizeText(font, vLines[i].substr(0, stop - last).c_str(), &w, &h);
					dst.w = w - dst.x;
					dst.y = i * h;
					dst2.h = dst.h;
					dst2.w = dst.w;
					highlightSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, dst.w, dst.h, 32, 0, 0, 0, 0);
					SDL_SetAlpha(highlightSurface, SDL_SRCALPHA, 128);
					SDL_FillRect(highlightSurface, &dst2, 0x0000ff);
					apply_surface(box2.x + dst.x, box2.y + dst.y, highlightSurface, screen);
					done = true;
				}
			}
			last += vLines[i].size();
		}
	}
	SDL_FreeSurface(highlightSurface);
}

bool LOK2ChatInput::sendChatMessage(std::string userName, std::string message, bool command) {
	LOK2ChatPacket sendPacket;
	sendPacket.username = userName;
	sendPacket.message = message;
	sendPacket.command = command;
	if(m_pChatMsgHandler->send(sendPacket)) return true;
	return false;
}

void LOK2ChatInput::doAction(int handle, int message) {
	printf("%d, %d\n", handle, message);
}
